#include "historymessagewidget.h"
#include "model/datacenter.h"
#include "messageeditarea.h"
#include "soundrecorder.h"
#include "mainwidget.h"
#include "toast.h"
#include <QStyleOption>
#include <QFileDialog>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QPushButton>
#include <QGridLayout>
#include <QScrollBar>
#include <QPainter>
#include <QString>
#include <QLabel>
#include <Qsize>

using namespace model;

MessageEditArea::MessageEditArea(QWidget *parent)
    :QWidget(parent)
{
    //1.设置必要属性
    this->setFixedHeight(200);
    this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);

    //2.创建垂直方向布局管理
    QVBoxLayout* vlayout = new QVBoxLayout();
    vlayout->setSpacing(0);
    vlayout->setContentsMargins(10, 0, 10, 10);
    this->setLayout(vlayout);

    //3.创建水平的布局管理器
    QHBoxLayout* hlayout = new QHBoxLayout();
    hlayout->setSpacing(0);
    hlayout->setAlignment(Qt::AlignLeft | Qt::AlignTop);
    hlayout->setContentsMargins(10, 0, 0, 0);
    vlayout->addLayout(hlayout);

    //4.把上方的四个按钮 创建好并添加到水平布局中
    QString btnStyle = "QPushButton { background-color: rgb(245, 245, 245); border: none; } QPushButton:pressed { background-color: rgb(255, 255, 255); border: none; }";

    QSize iconSize(28, 28);
    sendImageBtn = new QPushButton();
    sendImageBtn->setFixedSize(35, 35);
    sendImageBtn->setIconSize(iconSize);
    sendImageBtn->setIcon(QIcon(":/resource/image/image.png"));
    sendImageBtn->setStyleSheet(btnStyle);
    hlayout->addWidget(sendImageBtn);

    sendFileBtn = new QPushButton();
    sendFileBtn->setFixedSize(35, 35);
    sendFileBtn->setIconSize(iconSize);
    sendFileBtn->setIcon(QIcon(":/resource/image/file.png"));
    sendFileBtn->setStyleSheet(btnStyle);
    hlayout->addWidget(sendFileBtn);

    sendSpeechBtn = new QPushButton();
    sendSpeechBtn->setFixedSize(35, 35);
    sendSpeechBtn->setIconSize(iconSize);
    sendSpeechBtn->setIcon(QIcon(":/resource/image/sound.png"));
    sendSpeechBtn->setStyleSheet(btnStyle);
    hlayout->addWidget(sendSpeechBtn);

    showHistoryBtn = new QPushButton();
    showHistoryBtn->setFixedSize(35, 35);
    showHistoryBtn->setIconSize(iconSize);
    showHistoryBtn->setIcon(QIcon(":/resource/image/history.png"));
    showHistoryBtn->setStyleSheet(btnStyle);
    hlayout->addWidget(showHistoryBtn);

    textEdit = new QPlainTextEdit();
    textEdit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    textEdit->setStyleSheet("QPlainTextEdit { border: none; background-color: transparent; font-size: 14px; padding: 10px}");
    textEdit->verticalScrollBar()->setStyleSheet("QScrollBar:vertical { width: 2px; background-color: rgb(45, 45, 45); }");
    vlayout->addWidget(textEdit);

    //6. 添加正在录制中的提示标签
    tipLabel = new QLabel(this);
    tipLabel->setText("录音中...");
    tipLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    tipLabel->setAlignment(Qt::AlignCenter);
    tipLabel->setStyleSheet("QLabel { color: red; font-size: 28px; }");
    tipLabel->setVisible(false); //默认隐藏
    vlayout->addWidget(tipLabel);

    //7.添加发送文本消息的按钮
    sendTextBtn = new QPushButton();
    sendTextBtn->setText("发送");
    sendTextBtn->setFixedSize(120, 40);
    QString style = "QPushButton {font-size: 16px; color: rgb(7, 193, 96); border: none; background-color: rgb(233, 233, 233); border-radius: 10px;}";
    style += "QPushButton:hover {background-color: rgb(210, 210, 210);}";
    style += "QPushButton:pressed {background-color: rgb(190, 190, 190);}";
    sendTextBtn->setStyleSheet(style);
    vlayout->addWidget(sendTextBtn, 0, Qt::AlignRight | Qt::AlignBottom);

    //8.统一初始化信号槽
    initSignalSlots();
}

void MessageEditArea::initSignalSlots()
{
    DataCenter* dataCenter = DataCenter::getInstance();
    //////////////////////////////////////////
    ///点击显示历史消息按钮 弹出历史消息窗口
    //////////////////////////////////////////
    connect(showHistoryBtn, &QPushButton::clicked, this, [=]()
            {
                //判断当前有没有选中会话
                if (dataCenter->getCurrentChatSessionId().isEmpty())
                {
                    Toast::showMessage("当前未选中会话");
                    return;
                }
                HistoryMessageWidget* historymsgwidget = new HistoryMessageWidget(this);
                historymsgwidget->setWindowModality(Qt::ApplicationModal); //设置为模态对话框
                historymsgwidget->show();
            });
    //////////////////////////////////////////
    ///点击发送按钮 发送文本消息
    //////////////////////////////////////////
    connect(sendTextBtn, &QPushButton::clicked, this, &MessageEditArea::sendTextMessage); //复杂函数单独包装
    connect(dataCenter, &DataCenter::sendMessageDone, this, &MessageEditArea::addSelfMessage);

    //////////////////////////////////////////
    ///显示接受消息
    //////////////////////////////////////////
    connect(dataCenter, &DataCenter::receiveMessageDone, this, &MessageEditArea::addOtherMessage);

    //////////////////////////////////////////
    ///关联发送图片
    //////////////////////////////////////////
    connect(sendImageBtn, &QPushButton::clicked, this, &MessageEditArea::onSendImageClicked);

    //////////////////////////////////////////
    ///关联发送文件
    //////////////////////////////////////////
    connect(sendFileBtn, &QPushButton::clicked, this, &MessageEditArea::onSendFileClicked);

    //////////////////////////////////////////
    ///关联发送语音
    //////////////////////////////////////////
    connect(sendSpeechBtn, &QPushButton::pressed, this, &MessageEditArea::onStartRecordSpeech);
    connect(sendSpeechBtn, &QPushButton::released, this, &MessageEditArea::onStopRecordSpeech);
    SoundRecorder* soundRecorder = SoundRecorder::getInstance();
    connect(soundRecorder, &SoundRecorder::soundRecordDone, this, &MessageEditArea::sendSpeech);

}

void MessageEditArea::sendTextMessage()
{
    //1. 先确认是否有会话选中 如果没有选中的会话 则啥也不做
    DataCenter* dataCenter = DataCenter::getInstance();
    if (dataCenter->getCurrentChatSessionId().isEmpty())
    {
        LOG() << "没有选中任何会话, 无法发送消息!";
        Toast::showMessage("当前未选中会话");
        return;
    }
    // 2. 获取文本内容
    const QString& text = textEdit->toPlainText().trimmed();;
    if (text.isEmpty())
    {
        LOG() << "文本消息不能为空!";
        return;
    }
    //3.清空输入框内容
    textEdit->setPlainText("");
    //4.通过网络发送数据给服务器
    dataCenter->sendTextMessageAsync(dataCenter->getCurrentChatSessionId(), text);
}
//把自己发送的消息添加到
void MessageEditArea::addSelfMessage(Message_Type messageType, const QByteArray& content, const QString& extraInfo)
{
    DataCenter* dataCenter = DataCenter::getInstance();
    const QString currentChatSessionId  = dataCenter->getCurrentChatSessionId();

    //1. 构造message 对象
    Message msg = Message::makeMessage(messageType, currentChatSessionId, *dataCenter->getMyself(), content, extraInfo);
    //2. 把消息添加到最近消息列表中
    dataCenter->addMessage(msg);
    //3. 把新消息展示到主界面中
    auto messageShowArea = MainWidget::getInstance()->getMessageShowAreaWidget();
    messageShowArea->addMessage(false, msg); //自己发的消息 isLeft = false
    //4. 滚动到最底部
    messageShowArea->scrollToEnd();
    //5. 更新会话列表中的最后一条消息显示
    emit dataCenter->updateLastMessage(currentChatSessionId);
}

void MessageEditArea::addOtherMessage(const Message &message)
{
    DataCenter* dataCenter = DataCenter::getInstance();
    const QString currentChatSessionId  = dataCenter->getCurrentChatSessionId();

    //2. 把新消息展示到主界面中
    auto messageShowArea = MainWidget::getInstance()->getMessageShowAreaWidget();
    LOG() << "MessageEditArea::addOtherMessage -> lassMessage.chatSessionID" << message.chatSessionID
          << QString(message.content);
    messageShowArea->addMessage(true, message); //别人发的消息 isLeft = true
    //3. 滚动到最底部
    messageShowArea->scrollToEnd();
    //4. 更新会话列表中的最后一条消息显示
    Toast::showMessage("收到新消息");
}

void MessageEditArea::onSendImageClicked()
{
    //1. 先确认是否有会话选中 如果没有选中的会话 则啥也不做
    DataCenter* dataCenter = DataCenter::getInstance();
    if (dataCenter->getCurrentChatSessionId().isEmpty())
    {
        Toast::showMessage("当前未选中会话");
        return;
    }
    //2.弹出文件选择对话框 选择图片文件
    QString filePath = QFileDialog::getOpenFileName(this, "选择图片文件", QDir::homePath(), "图片文件 (*.png *.jpg *.jpeg *.bmp *.gif)");
    if (filePath.isEmpty())
    {
        LOG() << "未选择任何图片文件!";
        return;
    }
    //3.读取图片文件内容
    QByteArray imageContent = loadFileToByteArray(filePath);
    if (imageContent.isEmpty())
    {
        Toast::showMessage("读取图片文件失败");
        return;
    }

    //4.通过网络发送图片消息
    //////////////////////////////////////////////////////////////////////////////////
    ///发送图片消息会调用 DataCenter::sendImageMessageAsync 返回sendMessageDone 信号
    ///再通过上面的槽函数 addSelfMessage 把图片消息添加到界面上
    //////////////////////////////////////////////////////////////////////////////////

    LOG() << "MessageEditArea::onSendImageClicked 通过网络发送图片";
    dataCenter->sendImageMessageAsync(dataCenter->getCurrentChatSessionId(), imageContent);
}

void MessageEditArea::onSendFileClicked()
{
    DataCenter* dataCenter = DataCenter::getInstance();
    //1. 先确认是否有会话选中 如果没有选中的会话 则啥也不做
    if (dataCenter->getCurrentChatSessionId().isEmpty())
    {
        Toast::showMessage("当前未选中会话");
        return;
    }
    //2.弹出文件选择对话框 选择文件
    QString filePath = QFileDialog::getOpenFileName(this, "选择文件", QDir::homePath(), "所有文件 (*.*)");
    if (filePath.isEmpty())
    {
        LOG() << "未选择任何文件!";
        return;
    }
    //3.读取文件内容
    // 此处暂不考虑大文件的情况 几百MB 几个G的文件需要单独写接口 分片传输
    QByteArray fileContent = loadFileToByteArray(filePath);
    if (fileContent.isEmpty())
    {
        Toast::showMessage("读取文件失败");
        return;
    }
    //4. 获取文件名
    QString fileName = QFileInfo(filePath).fileName();

    //5.通过网络发送文件消息
    //////////////////////////////////////////////////////////////////////////////////
    /// 发送文件消息会调用 DataCenter::sendFileMessageAsync 返回sendMessageDone 信号
    /// 再通过上面的槽函数 addSelfMessage 把文件消息添加到界面上
    /////////////////////////////////////////////////////////////////////////////////////
    LOG() << "MessageEditArea::onSendFileClicked 通过网络发送文件";
    dataCenter->sendFileMessageAsync(dataCenter->getCurrentChatSessionId(), fileName, fileContent);
    Toast::showMessage("文件发送中 若文件较大 请耐心等待", 5000);
}

void MessageEditArea::onStartRecordSpeech()
{
    //1. 先确认是否有会话选中 如果没有选中的会话 则啥也不做
    DataCenter* dataCenter = DataCenter::getInstance();
    if (dataCenter->getCurrentChatSessionId().isEmpty())
    {
        Toast::showMessage("当前未选中会话");
        return;
    }
    //2.开始录制语音
        //切换图标
    SoundRecorder* soundRecorder = SoundRecorder::getInstance();
    soundRecorder->startRecord();
    sendSpeechBtn->setIcon(QIcon(":/resource/image/sound_active.png"));
    LOG() << "MessageEditArea::onStartRecordSpeech 开始录音";

    tipLabel->setVisible(true); //显示录音提示标签
    textEdit->hide();      //让文本输入框获取焦点 避免录音按钮被持续按下时界面卡死
}

void MessageEditArea::onStopRecordSpeech()
{
    //1. 先确认是否有会话选中 如果没有选中的会话 则啥也不做
    DataCenter* dataCenter = DataCenter::getInstance();
    if (dataCenter->getCurrentChatSessionId().isEmpty())
    {
        Toast::showMessage("当前未选中会话");
        return;
    }

    sendSpeechBtn->setIcon(QIcon(":/resource/image/sound.png"));
    //停止录制
    SoundRecorder* soundRecorder = SoundRecorder::getInstance();
    soundRecorder->stopRecord();
    LOG() << "MessageEditArea::onStopRecordSpeech 录音结束 获取语音数据";

    tipLabel->setVisible(false); //显示录音提示标签
    textEdit->show();
}

void MessageEditArea::sendSpeech(const QString &path)
{
    DataCenter* dataCenter = DataCenter::getInstance();
    //1.读取语音文件内容
    QByteArray speechContent = loadFileToByteArray(path);
    if (speechContent.isEmpty())
    {
        Toast::showMessage("读取语音文件失败");
        return;
    }
    //2.通过网络发送语音消息
    LOG() << "MessageEditArea::sendSpeech 通过网络发送语音";
    dataCenter->sendSpeechMessageAsync(dataCenter->getCurrentChatSessionId(), speechContent);
}














